{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "parameters"
    ]
   },
   "outputs": [],
   "source": [
    "epochs = 10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# পার্ট 6 - সিএনএন ব্যবহার করে এমএনআইএসটি সম্পর্কিত ফেডারেট লার্নিং\n",
    "\n",
    "## পাইটর্চ + পাইসাইফ্টের 10 টি লাইনে ফেডারেট লার্নিংয়ে আপগ্রেড করুন\n",
    "\n",
    "\n",
    "### প্রসঙ্গ\n",
    "\n",
    "ফেডারেটেড লার্নিং একটি অত্যন্ত উত্তেজনাপূর্ণ এবং উত্সাহব্যঞ্জক মেশিন লার্নিং কৌশল যা বিকেন্দ্রীভূত ডেটাতে শিখতে এমন বিল্ডিং সিস্টেমগুলিতে লক্ষ্য করে। ধারণাটি হ'ল ডেটাটি তার প্রযোজকের হাতে রয়েছে (যা _ কর্মী_ও নামে পরিচিত), যা গোপনীয়তা এবং মালিকানা উন্নত করতে সহায়তা করে এবং মডেলটি শ্রমিকদের মধ্যে ভাগ করে নেওয়া হয়েছে। একটি তাত্ক্ষণিক অ্যাপ্লিকেশন হ'ল আপনি পাঠ্য লেখার সময় আপনার মোবাইল ফোনে পরবর্তী শব্দটির পূর্বাভাস দেওয়া: আপনি প্রশিক্ষণের জন্য ব্যবহৃত ডেটা চান না - যেমন আপনার পাঠ্য বার্তা - কোনও কেন্দ্রীয় সার্ভারে প্রেরণ করা হোক।\n",
    "\n",
    "ফেডারেটড লার্নিংয়ের উত্থান তথ্যের সাথে গোপনীয়তা সচেতনতার প্রসারের সাথে দৃly়ভাবে সংযুক্ত, এবং ইইউতে জিডিপিআর যা মে 2018 সাল থেকে ডেটা সুরক্ষা প্রয়োগ করে, অনুঘটক হিসাবে কাজ করেছে। নিয়ন্ত্রণের পূর্বাভাস দেওয়ার জন্য, অ্যাপল বা গুগলের মতো বড় বড় অভিনেতা বিশেষত মোবাইল ব্যবহারকারীর গোপনীয়তা রক্ষার জন্য এই প্রযুক্তিতে ব্যাপক বিনিয়োগ শুরু করেছেন, তবে তারা তাদের সরঞ্জামগুলি উপলব্ধ করেনি। ওপেনমিনে আমরা বিশ্বাস করি যে যে কেউ মেশিন লার্নিং প্রকল্প পরিচালনা করতে ইচ্ছুক তিনি খুব অল্প প্রচেষ্টা সহ গোপনীয়তা সংরক্ষণের সরঞ্জামগুলি প্রয়োগ করতে সক্ষম হবেন। আমরা একক লাইনে ডেটা এনক্রিপ্ট করার জন্য সরঞ্জাম তৈরি করেছি [আমাদের ব্লগ পোস্টে উল্লিখিত হিসাবে](https://blog.openmined.org/training-cnns-using-spdz/) এবং আমরা এখন আমাদের ফেডারেট লার্নিং ফ্রেমওয়ার্ক প্রকাশ করি যা উত্সাহ অর্জন করে সুরক্ষিত এবং স্কেলযোগ্য মডেলগুলি তৈরিতে একটি স্বজ্ঞাত ইন্টারফেস সরবরাহ করতে নতুন পাইটর্চ 1.0 সংস্করণ।\n",
    "\n",
    "এই টিউটোরিয়ালে, আমরা সরাসরি ব্যবহার করব [পাইটর্চ ব্যবহার করে এমএনআইএসটিতে সিএনএন প্রশিক্ষণের প্রথাগত উদাহরণ](https://github.com/pytorch/example/blob/master/mnist/main.py) এবং দেখাবো এটি কতটা সহজ এটি আমাদের [পাইসাইফ্ট লাইব্রেরি](https://github.com/OpenMined/PySyft/) ব্যবহার করে এর সাথে ফেডারেট লার্নিং বাস্তবায়ন করা। আমরা উদাহরণের প্রতিটি অংশ জুড়ে যাব এবং কোডটি আন্ডারলাইন করব যা পরিবর্তিত হয়েছে।\n",
    "\n",
    "আপনি এই উপাদানগুলি [আমাদের ব্লগপোস্ট](https://blog.openmined.org/upgrade-to-fedrated-learning-in-10-lines) এও পেতে পারেন।\n",
    "\n",
    "লেখক:\n",
    "- থিও রাইফেল - গিটহাব: [@LaRiffle](https://github.com/LaRiffle)\n",
    "\n",
    "অনুবাদক:\n",
    "- সায়ন্তন দাস - গিটহাব: [@ucalyptus](https://github.com/ucalyptus)\n",
    "\n",
    "\n",
    "** ঠিক আছে, শুরু করা যাক! **"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### আমদানি এবং মডেল নির্দিষ্টকরণ\n",
    "\n",
    "প্রথমে আমরা অফিসিয়াল আমদানি করি"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "এবং পাইসাইফ্ট সম্পর্কিত নির্দিষ্টগুলির তুলনায়। বিশেষত আমরা দূরবর্তী কর্মীদের `এলিস` এবং` ববিকে সংজ্ঞায়িত করি `"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import syft as sy  # <-- NEW: import the Pysyft library\n",
    "hook = sy.TorchHook(torch)  # <-- NEW: hook PyTorch ie add extra functionalities to support Federated Learning\n",
    "bob = sy.VirtualWorker(hook, id=\"bob\")  # <-- NEW: define remote worker bob\n",
    "alice = sy.VirtualWorker(hook, id=\"alice\")  # <-- NEW: and alice"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আমরা শেখার কাজটির সেটিংটি সংজ্ঞায়িত করি"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Arguments():\n",
    "    def __init__(self):\n",
    "        self.batch_size = 64\n",
    "        self.test_batch_size = 1000\n",
    "        self.epochs = epochs\n",
    "        self.lr = 0.01\n",
    "        self.momentum = 0.5\n",
    "        self.no_cuda = False\n",
    "        self.seed = 1\n",
    "        self.log_interval = 30\n",
    "        self.save_model = False\n",
    "\n",
    "args = Arguments()\n",
    "\n",
    "use_cuda = not args.no_cuda and torch.cuda.is_available()\n",
    "\n",
    "torch.manual_seed(args.seed)\n",
    "\n",
    "device = torch.device(\"cuda\" if use_cuda else \"cpu\")\n",
    "\n",
    "kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ডেটা লোড করা এবং কর্মীদের কাছে প্রেরণ\n",
    "আমরা প্রথমে ডেটা লোড করি এবং প্রশিক্ষণ ডেটাসেটকে `। ফেডারেট` পদ্ধতিটি ব্যবহার করে কর্মীদের জুড়ে ফেডারেশনযুক্ত ডেটাসেট বিভক্তিতে রূপান্তর করি। এই ফেডারেটেড ডেটাসেটটি এখন একটি ফেডারেটেড ডেটা লোডারকে দেওয়া হয়। পরীক্ষার ডেটাসেট অপরিবর্তিত রয়েছে।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "federated_train_loader = sy.FederatedDataLoader( # <-- this is now a FederatedDataLoader \n",
    "    datasets.MNIST('../data', train=True, download=True,\n",
    "                   transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ]))\n",
    "    .federate((bob, alice)), # <-- NEW: we distribute the dataset across all the workers, it's now a FederatedDataset\n",
    "    batch_size=args.batch_size, shuffle=True, **kwargs)\n",
    "\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=False, transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ])),\n",
    "    batch_size=args.test_batch_size, shuffle=True, **kwargs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### সিএনএন স্পেসিফিকেশন\n",
    "এখানে আমরা সরকারী উদাহরণে ঠিক একই সিএনএন ব্যবহার করি।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(1, 20, 5, 1)\n",
    "        self.conv2 = nn.Conv2d(20, 50, 5, 1)\n",
    "        self.fc1 = nn.Linear(4*4*50, 500)\n",
    "        self.fc2 = nn.Linear(500, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = F.max_pool2d(x, 2, 2)\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = F.max_pool2d(x, 2, 2)\n",
    "        x = x.view(-1, 4*4*50)\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return F.log_softmax(x, dim=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ট্রেন এবং পরীক্ষার ক্রিয়াগুলি সংজ্ঞায়িত করুন\n",
    "ট্রেনের ক্রিয়াকলাপের জন্য, ডেটা ব্যাচগুলি `অ্যালিস` এবং` বোবি জুড়ে বিতরণ করা হয়েছে, তাই আপনাকে প্রতিটি ব্যাচের জন্য সঠিক জায়গায় মডেলটি প্রেরণ করতে হবে। তারপরে, আপনি স্থানীয় পাইটর্চ করছেন এমন একই সিনট্যাক্সের সাহায্যে আপনি সমস্ত ক্রিয়াকলাপ দূরবর্তীভাবে সম্পাদন করেন। আপনার কাজ শেষ হয়ে গেলে, আপনি আপডেট হওয়া মডেলটি ফিরে পেয়েছেন এবং উন্নতির সন্ধানের ক্ষতি।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(args, model, device, federated_train_loader, optimizer, epoch):\n",
    "    model.train()\n",
    "    for batch_idx, (data, target) in enumerate(federated_train_loader): # <-- now it is a distributed dataset\n",
    "        model.send(data.location) # <-- NEW: send the model to the right location\n",
    "        data, target = data.to(device), target.to(device)\n",
    "        optimizer.zero_grad()\n",
    "        output = model(data)\n",
    "        loss = F.nll_loss(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        model.get() # <-- NEW: get the model back\n",
    "        if batch_idx % args.log_interval == 0:\n",
    "            loss = loss.get() # <-- NEW: get the loss back\n",
    "            print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n",
    "                epoch, batch_idx * args.batch_size, len(federated_train_loader) * args.batch_size,\n",
    "                100. * batch_idx / len(federated_train_loader), loss.item()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "পরীক্ষার ফাংশন বদলায় না!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(args, model, device, test_loader):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader:\n",
    "            data, target = data.to(device), target.to(device)\n",
    "            output = model(data)\n",
    "            test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss\n",
    "            pred = output.argmax(1, keepdim=True) # get the index of the max log-probability \n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "\n",
    "    test_loss /= len(test_loader.dataset)\n",
    "\n",
    "    print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n",
    "        test_loss, correct, len(test_loader.dataset),\n",
    "        100. * correct / len(test_loader.dataset)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### প্রশিক্ষণ চালু করুন!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "model = Net().to(device)\n",
    "optimizer = optim.SGD(model.parameters(), lr=args.lr) # TODO momentum is not supported at the moment\n",
    "\n",
    "for epoch in range(1, args.epochs + 1):\n",
    "    train(args, model, device, federated_train_loader, optimizer, epoch)\n",
    "    test(args, model, device, test_loader)\n",
    "\n",
    "if (args.save_model):\n",
    "    torch.save(model.state_dict(), \"mnist_cnn.pt\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "এট ভয়েইল! আপনি এখানে, আপনি ফেডারেটেড লার্নিং ব্যবহার করে দূরবর্তী ডেটাতে একটি মডেল প্রশিক্ষণ দিয়েছেন!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## গত এক জিনিস\n",
    "আমি জানি যে আপনি জিজ্ঞাসা করতে মারা যাচ্ছেন এমন একটি প্রশ্ন রয়েছে: ** সাধারণ পাইটর্চের তুলনায় ফেডারেট লার্নিং করতে কত সময় লাগে? **\n",
    "\n",
    "গণনার সময়টি আসলে ** স্বাভাবিক পাইটর্চ সম্পাদনের জন্য ব্যবহৃত ** বারের চেয়ে দ্বিগুণ কম! আরও স্পষ্টভাবে, এটি 1.9 গুণ বেশি সময় নেয়, যা আমরা যুক্ত করতে সক্ষম হওয়া বৈশিষ্ট্যের তুলনায় খুব কম।"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## উপসংহার\n",
    "\n",
    "যেমন আপনি পর্যবেক্ষণ করেন, আমরা এমএনআইএসটিতে অফিসিয়াল পাইটোর্চ উদাহরণটিকে বাস্তব ফেডারেট লার্নিং সেটিংয়ে আপগ্রেড করার জন্য 10 টি লাইন কোড সংশোধন করেছি!\n",
    "\n",
    "অবশ্যই, আমরা ভাবতে পারি এমন ডজনগুলি উন্নতি রয়েছে। আমরা গণনাটি শ্রমিকদের সমান্তরালভাবে পরিচালিত করতে এবং ফেডারেটের গড় সম্পাদন করতে, প্রতি মডেলকে প্রতি `n` ব্যাচকে কেবল আপডেট করতে, শ্রমিকদের মধ্যে যোগাযোগের জন্য আমরা যে বার্তাগুলি ব্যবহার করি ইত্যাদি হ্রাস করতে পারি etc. ফেডরেটেড লার্নিংকে উত্পাদন পরিবেশের জন্য প্রস্তুত করার জন্য পুনরায় কাজ করছি এবং তারা প্রকাশের সাথে সাথে আমরা সেগুলি সম্পর্কে লিখব!\n",
    "\n",
    "আপনার এখন ফেডারেট লার্নিং নিজেই করতে সক্ষম হওয়া উচিত! আপনি যদি এটি উপভোগ করেন এবং গোপনীয়তা সংরক্ষণ, এআই এবং এআই সরবরাহ চেইনের (ডেটা) বিকেন্দ্রীভূত মালিকানার দিকে আন্দোলনে যোগ দিতে চান, আপনি নিম্নলিখিত উপায়ে এটি করতে পারেন!\n",
    "\n",
    "### গিটহাবে স্টার পাইসাইফ্ট\n",
    "\n",
    "আমাদের সম্প্রদায়কে সাহায্য করার সবচেয়ে সহজ উপায় হ'ল কেবল স্টোরগুলি স্টোর করে! এটি আমরা যে শীতল সরঞ্জামগুলি তৈরি করছি তার সচেতনতা বাড়াতে সহায়তা করে।\n",
    "\n",
    "- [স্টার পাইসাইফ্ট](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### গিটহাবে আমাদের টিউটোরিয়ালগুলি চয়ন করুন!\n",
    "\n",
    "ফেডারেটেড এবং প্রাইভেসি-প্রিজারভেভিং লার্নিংয়ের চেহারা কেমন হওয়া উচিত এবং আমরা এটির জন্য ইটগুলি কীভাবে তৈরি করছি সে সম্পর্কে আরও ভাল ধারণা পেতে আমরা সত্যিই দুর্দান্ত টিউটোরিয়াল তৈরি করেছি।\n",
    "\n",
    "- [পাইসাইফ্ট টিউটোরিয়াল চেকআউট করুন](https://github.com/OpenMined/PySyft/tree/master/example/tutorials)\n",
    "\n",
    "\n",
    "### আমাদের স্ল্যাচে যোগ দিন!\n",
    "\n",
    "সর্বশেষতম অগ্রগতিতে আপ টু ডেট রাখার সর্বোত্তম উপায় হ'ল আমাদের সম্প্রদায়ে যোগদান করা!\n",
    "\n",
    "- [স্ল্যাক.ওপেনমিনিড.অর্ডারে যোগ দিন](http://slack.openmined.org)\n",
    "\n",
    "### একটি কোড প্রকল্পে যোগদান করুন!\n",
    "\n",
    "আমাদের সম্প্রদায়ে অবদান রাখার সর্বোত্তম উপায় হ'ল কোড অবদানকারী হয়ে উঠুন! আপনি যদি মিনি-প্রকল্পগুলি \"ওয়ান অফ\" শুরু করতে চান তবে আপনি পাইসাইফ্ট গিটহাব ইস্যু পৃষ্ঠাতে যেতে পারেন এবং First গুড ফার্স্ট ইস্যু marked চিহ্নিত বিষয়গুলি সন্ধান করতে পারেন `\n",
    "\n",
    "- [ভাল প্রথম ইস্যুর টিকিট](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n",
    "\n",
    "### দান করুন\n",
    "\n",
    "আপনার যদি আমাদের কোডবেসে অবদান রাখার সময় না থাকে তবে তবুও সমর্থন leণ দিতে চান, আপনি আমাদের ওপেন কালেক্টিভেরও ব্যাকের হয়ে উঠতে পারেন। সমস্ত অনুদান আমাদের ওয়েব হোস্টিং এবং অন্যান্য সম্প্রদায় ব্যয় যেমন হ্যাকাথনস এবং মেটআপগুলির দিকে যায়!\n",
    "\n",
    "- [ওপেনমাইন্ডের মুক্ত সমাহার পৃষ্ঠার মাধ্যমে দান করুন](https://opencollective.com/openmined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
